package com.zhang.handler;

import com.zhang.ChannelManage;
import com.zhang.common.Constant;
import com.zhang.common.codec.MyHttpResponseEncoder;
import com.zhang.common.config.GlobalConfig;
import com.zhang.common.message.ProxyMessage;
import com.zhang.common.message.ProxyMessageUtil;
import io.netty.buffer.ByteBuf;
import io.netty.channel.Channel;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInboundHandlerAdapter;
import io.netty.handler.codec.http.FullHttpResponse;
import io.netty.handler.codec.http.HttpHeaderNames;
import io.netty.util.ReferenceCountUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.ArrayList;
import java.util.List;

/**
 * 把真实服务器的http数据 推给 ngrok服务器
 * @author 98265
 */
public class HttpSendHandler extends ChannelInboundHandlerAdapter {

    /**
     * 日志对象
     */
    static private Logger log = LoggerFactory.getLogger(HttpSendHandler.class);
    /**
     * http response 编码器
     */
    private MyHttpResponseEncoder httpResponseEncoder = new MyHttpResponseEncoder();

    @Override
    public void channelInactive(ChannelHandlerContext ctx) throws Exception {
        log.debug("真实服务端出现断开");
        ChannelManage.setRealServerChannel(null);
    }

    @Override
    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
       log.debug("代理客户端跟真实服务端出现异常断开");
       ChannelManage.setRealServerChannel(null);
    }

    @Override
    public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
        log.debug("进到HttpSendHandler");
        if(msg instanceof FullHttpResponse){
            FullHttpResponse response = (FullHttpResponse) msg;
            httpHandle(ctx,response);
        }else{
            ReferenceCountUtil.release(msg);
            log.error("不支持的http消息，丢弃");
        }

    }

    /**
     * http 处理 发送
     * @param ctx
     * @param response
     * @throws Exception
     */
    private void httpHandle(ChannelHandlerContext ctx, FullHttpResponse response) throws Exception {

        //客户端与代理服务器的channel
        Channel ngrokServerChannel = ChannelManage.getNgrokServerChannel();
        int code = response.status().code();
        //如果响应码是302或303说明请求的真实服务器进行了重定向 故需要修改下location的属性代理客户端注册的域名
        if (code == 302 || code == 303) {
            String httpPort = ngrokServerChannel.attr(Constant.HTTP_PORT).get()+"";
            String proxyServer = GlobalConfig.props.getStr("subdomain") + "." + GlobalConfig.props.getStr("serverdomain")+":"+httpPort;
            String localtion = String.valueOf(response.headers().get(HttpHeaderNames.LOCATION));
            int index = localtion.indexOf("/", 8);
            localtion = "http://" + proxyServer + localtion.substring(index);
            response.headers().set(HttpHeaderNames.LOCATION,localtion);
        }


        List<Object> list = new ArrayList<>();
        httpResponseEncoder.encode(ctx, response, list);
        for (Object o : list) {

            ByteBuf buf = (ByteBuf) o;
            byte[] data = new byte[buf.readableBytes()];
            buf.readBytes(data);
            buf.release();
            Long httpId = (Long)ctx.channel().attr(Constant.HTTP_ID).get();
            log.debug("转发HTTP消息到代理服务器 {}",httpId);
            ProxyMessage proxyMessage = ProxyMessageUtil.buildTransferRespSuccess(httpId, data);
            ngrokServerChannel.writeAndFlush(proxyMessage);
        }

    }
}
